package org.newlucene.core.index;

import java.io.IOException;

import org.newlucene.core.store.Directory;
import org.newlucene.core.store.OutputStream;

/** This stores a monotonically increasing set of <Term, TermInfo> pairs in a
  Directory.  A TermInfos can be written once, in order.  */

final class TermInfosIndexWriter 
{
	private FieldInfos fieldInfos;
	private OutputStream output;
	private Term lastTerm = new Term("", "");
	private TermInfo lastTi = new TermInfo();
	private int size = 0;
  
	private long lastIndexPointer = 0;

	private TermInfosWriter tisWriter = null;

	public TermInfosIndexWriter(Directory directory, String segment, FieldInfos fis, TermInfosWriter tisWriter) throws IOException 
	{
		this.tisWriter = tisWriter;
		
		// initialize
		fieldInfos = fis;
		output = directory.createFile(segment + ".tii");
		output.writeInt(0);				  // leave space for size
	}

	/** Adds a new <Term, TermInfo> pair to the set.
    Term must be lexicographically greater than all previous Terms added.
    TermInfo pointers must be positive and greater than all previous.*/
	final void add(Term term, TermInfo ti) throws IOException, SecurityException 
	{
		if (ti.freqPointer < lastTi.freqPointer)
		{
			throw new IOException("freqPointer out of order");
		}

		writeTerm(term);				  // write term
		output.writeVInt(ti.docCount);		  // write doc freq
		output.writeVLong(ti.freqPointer - lastTi.freqPointer); // write pointers


		output.writeVLong(tisWriter.output.getFilePointer() - lastIndexPointer);
		lastIndexPointer = tisWriter.output.getFilePointer(); // write pointer

		lastTi.set(ti.docCount, ti.freqPointer);
		size++;
	}

	private final void writeTerm(Term term) throws IOException 
	{
		int start = stringDifference(lastTerm.text, term.text);
		int length = term.text.length() - start;
    
		output.writeVInt(start);			  // write shared prefix length
		output.writeVInt(length);			  // write delta length
		output.writeChars(term.text, start, length);  // write delta chars
		output.writeVInt(fieldInfos.getFieldInfo(term.field).number); // write field num

		lastTerm = term;
	}

	private static final int stringDifference(String s1, String s2) 
	{
		int len1 = s1.length();
		int len2 = s2.length();
		int len = len1 < len2 ? len1 : len2;
		for (int i = 0; i < len; i++)
		{
			if (s1.charAt(i) != s2.charAt(i))
			{
				return i;
			}
		}
		return len;
	}

	/** Called to complete TermInfos creation. */
	final void close() throws IOException, SecurityException 
	{
		output.seek(0);				  // write size at start
		output.writeInt(size);
		output.close();    
	}
}
